//==============================================================================
// Copyright (c) 2008-2013 Niall Ryan. All Rights Reserved.
//==============================================================================

#ifndef HYDRA_LOCKS_PETERSONLOCK_H
#define HYDRA_LOCKS_PETERSONLOCK_H 1

#include "hydra/atomic/Atomic.h"

namespace Hydra
{
	class PetersonLock
	{
	public:
		PetersonLock()
		{
			m_flag[0] = m_flag[1] = 0;
		}
		void lock(int id)
		{
			assert((id==0) || (id==1));
			int otherId = 1 - id;

			m_flag[id] = true;
			m_victim.store<FullFence>(id);	//memory barrier is necessary here, otherwise the store to m_victim and read from m_flag[otherId] can
											// be re-ordered, standard acquire/release semantics do not prevent this
			//spin until lock is acquired
			while( m_flag[otherId] && (m_victim == id) )	{ }
		}
		void unlock(int id)
		{
			assert((id==0) || (id==1));
			m_flag[id] = false;
		}
	private:
		Atomic<bool> m_flag[2];
		Atomic<int> m_victim;
	};
}

#endif
